﻿using System;
using System.Xml.Serialization;
using System.Linq;
using System.Collections.Generic;
using System.Text.RegularExpressions;

/// <summary>
/// Summary description for Tweets
/// </summary>
public class Tweets
{
    public static Common.TweetCreateStatus CreateTweet(string text, string userId)
    {
        List<Common.User> Users = DataTier.GetUsers();

        // validate user exists
        if (Users.Count(n => n.userId == userId) == 0)
        {
            return Common.TweetCreateStatus.UserDoesntExist;
        }

        // get stored tweets
        List<Common.Tweet> Tweets = DataTier.GetTweets();

        // generate unique GUID
        string newGuid = Common.Utilities.GenerateGUID();
        while (Tweets.Count(n => n.tweetId == newGuid) != 0)
        {
            newGuid = Common.Utilities.GenerateGUID();
        }

        // create tweet object
        Common.Tweet tweet = new Common.Tweet();
        tweet.userId = userId;
        tweet.timestamp = DateTime.Now.ToUniversalTime().ToString();
        tweet.text = text;
        tweet.tweetId = newGuid;
        Tweets.Add(tweet);

        // store tweets
        DataTier.SaveTweets(Tweets);

        // return success status
        return Common.TweetCreateStatus.Created;
    }

    public static List<string> GetTopHashTags(int amountToReturn)
    {
        // remove time from todays UTC 
        string todayUTC = DateTime.Now.ToUniversalTime().ToString();
        todayUTC = todayUTC.Substring(0,todayUTC.IndexOf(" "));
     
        // contains top N hashtags
        List<string> topHashTags = new List<string>();

        // get stored tweets
        List<Common.Tweet> Tweets = DataTier.GetTweets();
        
        // contains all hashtags
        List<string> hashTagsList = new List<string>();
        
        // extract todays hashtags from tweets  
        Tweets.Where(n => n.timestamp.Substring(0,n.timestamp.IndexOf(" ")) == todayUTC ).ToList().ForEach(n => hashTagsList.AddRange(Common.Utilities.GetHashTagsInText(n.text)));
       // Tweets.ForEach(n =>  hashTagsList.AddRange(Common.Utilities.GetHashTagsInText(n.text))); // gets top hashtags

        // group by hash tag, then order by count, then take top N, then add them to the return list
        hashTagsList.GroupBy(n => n).OrderByDescending(n => n.Count()).Take(amountToReturn).ToList().ForEach(n => topHashTags.Add(n.Key));
        
        // return top N hashtags
        return topHashTags;
    }

    public static List<Common.Tweet> GetMentions(string user)
    {
        // get stored tweets
        List<Common.Tweet> Tweets = DataTier.GetTweets();

        List<Common.Tweet> userMentions = new List<Common.Tweet>();

        // filter by user, order descending by date, then add them to the return list
        Tweets.Where(n => (n.text.StartsWith(user + " ") && !n.text.StartsWith(user + ": ")) || (n.text.EndsWith(" " + user)) || n.text.Contains(" " + user + " ")).OrderByDescending(n => n.timestamp).ToList().ForEach(n => userMentions.Add(n));
        return userMentions;
    }

    public static List<Common.Tweet> GetReTweets(string user)
    {
        // get stored tweets
        List<Common.Tweet> Tweets = DataTier.GetTweets();
        List<Common.Tweet> userMentions = new List<Common.Tweet>();

        // filter by user, order descending by date, then add them to the return list
        Tweets.Where(n => n.text.StartsWith(user + ": ")).OrderByDescending(n => n.timestamp).ToList().ForEach(n => userMentions.Add(n));
        return userMentions;
    }

    public static List<Common.Tweet> GetFilteredTweets(string filterText)
    {
        // get stored tweets
        List<Common.Tweet> Tweets = DataTier.GetTweets();
        List<Common.Tweet> foundTweets = new List<Common.Tweet>();
 
        // filter by filterText parameter then add them to the return list
        Tweets.Where(n => n.text.Contains(filterText)).ToList().ForEach(n => foundTweets.Add(n));
        return foundTweets;
    }

    public static List<Common.Tweet> SearchTweets(string filterText, bool sortDescending, int page, int resultsPerPage)
    {
        // get filtered tweets
        List<Common.Tweet> foundTweets = GetFilteredTweets(filterText);

        // sort by date 
        if (sortDescending)
        {
            foundTweets.OrderByDescending(n => n.timestamp);
        }
        else
        {
            foundTweets.OrderBy(n => n.timestamp);
        }

        List<Common.Tweet> searchResults = new List<Common.Tweet>();

        // skip X(page * resultsPerPage) results per page then read Y(resultsPerPage), add them to the return list
        foundTweets.Skip(page * resultsPerPage).Take(resultsPerPage).ToList().ForEach(n => searchResults.Add(n) );

        return searchResults;
    }
    
    public static List<Common.Tweet> GetTimeLine(string userName, int page, int resultsPerPage)
    {
        // get stored tweets
        List<Common.Tweet> tweets = DataTier.GetTweets();

        List<Common.Tweet> timeline = new List<Common.Tweet>();
        
        // get current user
        Common.User user = Users.GetUserProfile(userName);

        // get all tweets by user or followed users, order by date then read Y(resultsPerPage) starting at page X(page) then add them to the return list
        tweets.Where(n => n.userId == user.userId || user.usersFollowed.Contains(n.userId)).OrderByDescending(n => n.timestamp).Skip(page*resultsPerPage).Take(resultsPerPage).ToList().ForEach(n => timeline.Add(n));
        return timeline;
    }
}
